package com.asmtest.visitor;

import lombok.extern.slf4j.Slf4j;
import org.apache.maven.repository.internal.MavenRepositorySystemUtils;
import org.eclipse.aether.DefaultRepositorySystemSession;
import org.eclipse.aether.RepositorySystem;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.connector.basic.BasicRepositoryConnectorFactory;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyFilter;
import org.eclipse.aether.repository.LocalRepository;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.repository.RepositoryPolicy;
import org.eclipse.aether.resolution.ArtifactRequest;
import org.eclipse.aether.resolution.ArtifactResolutionException;
import org.eclipse.aether.resolution.ArtifactResult;
import org.eclipse.aether.resolution.DependencyRequest;
import org.eclipse.aether.resolution.DependencyResolutionException;
import org.eclipse.aether.spi.connector.RepositoryConnectorFactory;
import org.eclipse.aether.spi.connector.transport.TransporterFactory;
import org.eclipse.aether.transport.file.FileTransporterFactory;
import org.eclipse.aether.transport.http.HttpTransporterFactory;
import org.eclipse.aether.util.artifact.JavaScopes;
import org.eclipse.aether.util.filter.DependencyFilterUtils;

import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;

/**
 * @author yutianhong
 * @version 1.0
 * @since 2023/12/29 12:45
 */
@Slf4j
public class MavenArtifactDownloader {

    private static final RepositorySystem repoSystem = newRepositorySystem();


    /**
     * @throws ArtifactResolutionException 如果在仓库找不到jar包，就会抛出这个异常
     */
    public static File downloadJar(String groupId, String artifactId, String version, String classifier, String destDir, String repositoryUrl)
            throws ArtifactResolutionException {
        validateParameters(groupId, artifactId, version, destDir, repositoryUrl);

        RepositoryPolicy policy = new RepositoryPolicy(
                true, RepositoryPolicy.UPDATE_POLICY_ALWAYS, RepositoryPolicy.UPDATE_POLICY_ALWAYS);
        RemoteRepository remoteRepository = new RemoteRepository.Builder("central", "default", repositoryUrl)
                .setReleasePolicy(policy)
                .setSnapshotPolicy(policy)
                .build();

        Artifact artifact = (classifier != null && !classifier.isEmpty())
                ? new DefaultArtifact(groupId, artifactId, classifier, "jar", version)
                : new DefaultArtifact(groupId, artifactId, "jar", version);

        DefaultRepositorySystemSession session = newRepositorySystemSession(destDir);
        ArtifactRequest artifactRequest = new ArtifactRequest()
                .addRepository(remoteRepository)
                .setArtifact(artifact);
        ArtifactResult artifactResult = repoSystem.resolveArtifact(session, artifactRequest);

        if (artifactResult == null || artifactResult.getArtifact() == null) {
            throw new RuntimeException("Unable to get the JAR file." +
                    " groupId: " + groupId + ", artifactId: " + artifactId + ", version: " + version + ", classifier: " + classifier);
        }
        return artifactResult.getArtifact().getFile();
    }

    public static List<File> downloadJarWithDependencies(String groupId, String artifactId, String version, String classifier, String destDir, String repositoryUrl) {
        validateParameters(groupId, artifactId, version, destDir, repositoryUrl);

        RemoteRepository central = new RemoteRepository.Builder("central", "default", repositoryUrl).build();

        Artifact artifact = (classifier != null && !classifier.isEmpty())
                ? new DefaultArtifact(groupId, artifactId, classifier, "jar", version)
                : new DefaultArtifact(groupId, artifactId, "jar", version);

        Dependency dependency = new Dependency(artifact, JavaScopes.COMPILE);

        CollectRequest collectRequest = new CollectRequest();
        collectRequest.setRoot(dependency);
        collectRequest.addRepository(central);

        DependencyFilter classpathFilter = DependencyFilterUtils.classpathFilter(JavaScopes.COMPILE);

        DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, classpathFilter);

        DefaultRepositorySystemSession session = newRepositorySystemSession(destDir);
        try {
            List<ArtifactResult> artifactResults = repoSystem.resolveDependencies(session, dependencyRequest).getArtifactResults();

            List<File> files = new ArrayList<>(artifactResults.size());
            for (ArtifactResult artifactResult : artifactResults) {
                File file = artifactResult.getArtifact().getFile();
                files.add(file);
                System.out.println("Downloaded: " + file);
            }
            return files;
        } catch (DependencyResolutionException e) {
            log.error("exception occurs resolve maven dependencies", e);
            return Collections.emptyList();
        }
    }

    /**
     * @return 仓库系统
     */
    private static RepositorySystem newRepositorySystem() {
        return MavenRepositorySystemUtils.newServiceLocator()
                .addService(RepositoryConnectorFactory.class, BasicRepositoryConnectorFactory.class)
                .addService(TransporterFactory.class, FileTransporterFactory.class)
                .addService(TransporterFactory.class, HttpTransporterFactory.class)
                .getService(RepositorySystem.class);
    }

    /**
     * @return 连接session
     */
    private static DefaultRepositorySystemSession newRepositorySystemSession(String destDir) {
        DefaultRepositorySystemSession session = MavenRepositorySystemUtils.newSession();
        LocalRepository localRepo = new LocalRepository(destDir);
        session.setUpdatePolicy(RepositoryPolicy.UPDATE_POLICY_ALWAYS);
        session.setLocalRepositoryManager(repoSystem.newLocalRepositoryManager(session, localRepo));
        return session;
    }

    private static void validateParameters(String groupId, String artifactId, String version, String targetPath, String repositoryUrl) {
        Objects.requireNonNull(groupId, "groupId must not be null");
        Objects.requireNonNull(artifactId, "artifactId must not be null");
        Objects.requireNonNull(version, "version must not be null");
        Objects.requireNonNull(targetPath, "destDir must not be null");
        Objects.requireNonNull(repositoryUrl, "repositoryUrl must not be null");
    }

    private MavenArtifactDownloader() {
    }

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        List<File> files = downloadJarWithDependencies(
                "com.alibaba.aecp.sdk",
                "pur-pr-sdk",
                "1.0.30-Dutsin-SNAPSHOT",
                null,
                "/Users/yth/IdeaProjects/Desktop/temp",
                "http://repo.alibaba-inc.com/nexus/content/groups/alirepositiry/"
        );
        long end = System.currentTimeMillis();
        System.out.println("download jar success. total cost: " + (end - start));
//        for (File file : files) {
//            FileDeleteStrategy.FORCE.deleteQuietly(file);
//        }
    }
}
